using System;

using LocalBoard.Domain;
using LocalBoard.Persistence;

namespace LocalBoard.Controller
{
	/// <summary>
	/// Summary description for BoardSecurity.
	/// </summary>
	public class BoardSecurity
	{
		private Board _currentBoard;
		private Profile _user = null;
		private ClubController _clubController;
		protected ClubController ClubController
		{
			get {return _clubController;}
		}
		private readonly string _anonymousUsername = "anonymous";

		public BoardSecurity(Board currentBoard, ClubController clubController)
		{
			Initialize(currentBoard, clubController);
		}
		public BoardSecurity(Board currentBoard, ClubController clubController, Profile user)
		{
			Initialize(currentBoard, clubController);
			SetTargetUser(user);
		}

		public void SetTargetUser(Profile user)
		{
			if(user == null)
				throw new ArgumentNullException("user");
			_user = user;
		}

		public bool CanUserAccessBoard()
		{
			return CanUserAccessBoard(_user);
		}
		public virtual bool CanUserAccessBoard(Profile user)
		{
			if(user == null)
				throw new ArgumentNullException("user");

			if(_currentBoard.AccessRoleId == 0)
				return true;
			if(UserRole.UserIsAdministrator(user))
				return true;
			if(_clubController.UserIsClubManager(user))
				return true;
			if(_currentBoard.Manager != null
				&& _currentBoard.Manager.Id == user.Id)
				return true;
			if(_clubController.IsUserInClubRole(user.Id, _currentBoard.AccessRoleId))
				return true;
			if(_clubController.IsUserInClubRole(user.Id, _currentBoard.PostRoleId))
				return true;
			return false;
		}

		public bool CanUserViewMessage(Message message)
		{
			return CanUserViewMessage(_user, message);
		}
		public bool CanUserViewMessage(Profile user, Message message)
		{
			if(user == null)
				throw new ArgumentNullException("user");
			if(message == null)
				throw new ArgumentNullException("message");

			if(!CanUserAccessBoard(user))
				return false;
			return true;
		}

		public bool CanUserPostMessage()
		{
			return CanUserPostMessage(_user);
		}
		public virtual bool CanUserPostMessage(Profile user)
		{
			if(user == null)
				throw new ArgumentNullException("user");

			if(!CanUserAccessBoard(user))
				return false;
			if(_currentBoard.PostRoleId == 0)
				return true;
			if(user.IsInRole(UserRole.ADMIN_ROLE_NAME))
				return true;
			if(_clubController.IsUserInClubRole(user.Id, UserRole.CLUB_MANAGER_ROLE_NAME))
				return true;
			if(_currentBoard.Manager != null
				&& _currentBoard.Manager.Id == user.Id)
				return true;
			if(_clubController.IsUserInClubRole(user.Id, _currentBoard.PostRoleId))
				return true;
			return false;
		}

		public bool CanUserEditMessage(Message message)
		{
			return CanUserEditMessage(_user, message);
		}
		public bool CanUserEditMessage(Profile user, Message message)
		{
			if(user == null || message == null)
				throw new ArgumentNullException("user or message");

			if(message.Author == null)
				return true;
			if(message.Author.UserId.ToLower() == _anonymousUsername)
				return true;
			if(user.UserId == message.Author.UserId)
				return true;
			return false;
		}

		public bool CanUserDeleteMessage(Message message)
		{
			return CanUserDeleteMessage(_user, message);
		}
		public virtual bool CanUserDeleteMessage(Profile user, Message message)
		{
			if(user == null || message == null)
				throw new ArgumentNullException("user or message");

			if(message.Author == null)
				return true;
			if(message.Author.UserId.ToLower() == _anonymousUsername)
				return true;
			if(user.IsInRole(UserRole.ADMIN_ROLE_NAME))
				return true;
			if(_clubController.IsUserInClubRole(user.Id, UserRole.CLUB_MANAGER_ROLE_NAME))
				return true;
			if(_currentBoard.Manager != null
				&& _currentBoard.Manager.Id == user.Id)
				return true;
			if(user.UserId == message.Author.UserId)
				return true;
			return false;
		}

		public bool CanUserPostReply()
		{
			return CanUserPostReply(_user);
		}
		public bool CanUserPostReply(Profile user)
		{
			if(user == null)
				throw new ArgumentNullException("user");
//TODO: implement close reply function
			return CanUserPostMessage(user);
		}

		public bool CanUserPostComment()
		{
			return CanUserPostComment(_user);
		}
		public bool CanUserPostComment(Profile user)
		{
			if(user == null)
				throw new ArgumentNullException("user");
//TODO: implement close comment function
			return CanUserPostMessage(user);
		}

		public bool CanUserDeleteComment(Comment comment)
		{
			return CanUserDeleteComment(_user, comment);
		}
		public virtual bool CanUserDeleteComment(Profile user, Comment comment)
		{
			if(user == null || comment == null)
				throw new ArgumentNullException("user or message");

			if(comment.Author == null)
				return true;
			if(comment.Author.UserId.ToLower() == _anonymousUsername)
				return true;
			if(user.IsInRole(UserRole.ADMIN_ROLE_NAME))
				return true;
			if(_clubController.IsUserInClubRole(user.Id, UserRole.CLUB_MANAGER_ROLE_NAME))
				return true;
			if(_currentBoard.Manager != null
				&& _currentBoard.Manager.Id == user.Id)
				return true;
			if(user.UserId == comment.Author.UserId)
				return true;
			return false;
		}

		public bool CanUserRateArticle(Message message)
		{
			return CanUserRateArticle(_user, message);
		}
		public bool CanUserRateArticle(Profile profile, Message message)
		{
			if(profile == null)
				throw new ArgumentNullException("profile");
			if(message == null)
				throw new ArgumentNullException("message");

			if(!CanUserViewMessage(profile, message))
				return false;
			if(IsUserMessageAuthor(profile, message))
				return false;
			return true;
		}

		private static bool IsUserMessageAuthor(Profile profile, Message message)
		{
			return message.Author != null
				&& message.Author.Id == profile.Id;
		}

		private void Initialize(Board currentBoard, ClubController clubController)
		{
//			if(currentBoard == null)
//				throw new ArgumentNullException("currentBoard");
			if(clubController == null)
				throw new ArgumentNullException("clubController");
			_currentBoard = currentBoard;
			_clubController = clubController;
		}
	}
}
